package com.example.flutter_pangle;

import androidx.annotation.NonNull;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.bytedance.sdk.shortplay.api.PSSDK;
import com.bytedance.sdk.shortplay.api.ShortPlay;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;

/** FlutterPanglePlugin */
public class FlutterPanglePlugin implements FlutterPlugin, MethodCallHandler, io.flutter.embedding.engine.plugins.activity.ActivityAware {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;
  private Context appContext;
  private android.app.Activity activity;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_pangle");
    channel.setMethodCallHandler(this);
    appContext = flutterPluginBinding.getApplicationContext();
    // Register PlatformView factory
    flutterPluginBinding.getPlatformViewRegistry().registerViewFactory(
        "flutter_pangle/detail_fragment",
        new DetailFragmentFactory(flutterPluginBinding.getBinaryMessenger(), () -> activity)
    );
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    switch (call.method) {
      case "initializeSDK":
        initializeSDK(call, result);
        break;
      case "setEligibleAudience":
        setEligibleAudience(call, result);
        break;
      case "setContentLanguages":
        setContentLanguages(call, result);
        break;
      case "setContentLanguage":
        setContentLanguage(call, result);
        break;
      case "getCurrentLanguage":
        result.success(getCurrentLanguage());
        break;
      case "requestFeedList":
        requestFeedList(call, result);
        break;
      case "requestFeedListWithFilters":
        requestFeedListWithFilters(call, result);
        break;
      case "requestPopularDrama":
        requestPopularDrama(call, result);
        break;
      case "requestNewFeedList":
        requestNewFeedList(call, result);
        break;
      case "requestDramaWithTag":
        requestDramaWithTag(call, result);
        break;
      case "getCategoryList":
        getCategoryList(call, result);
        break;
      case "requestSearchDrama":
        requestSearchDrama(call, result);
        break;
      case "checkPlayStatus":
        checkPlayStatus(call, result);
        break;
      case "setCollected":
        setCollected(call, result);
        break;
      case "clearLocalCache":
        clearLocalCache(call, result);
        break;
      default:
        result.notImplemented();
        break;
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  // ActivityAware
  @Override
  public void onAttachedToActivity(@NonNull io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding binding) {
    this.activity = binding.getActivity();
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() { this.activity = null; }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding binding) {
    this.activity = binding.getActivity();
  }

  @Override
  public void onDetachedFromActivity() { this.activity = null; }

  private void initializeSDK(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    String appId = asString(args.get("appId"));
    String vodAppId = asString(args.get("vodAppId"));
    String securityKey = asString(args.get("securityKey"));
    String licenseAssertPath = asString(args.get("licenseAssertPath"));
    String userId = asString(args.get("userId"));
    Boolean debug = asBoolean(args.get("debug"));

    try {
      PSSDK.Config.Builder builder = new PSSDK.Config.Builder();
      builder.appId(appId)
          .vodAppId(vodAppId)
          .securityKey(securityKey)
          .userId(userId)
          .licenseAssertPath(licenseAssertPath)
          .debug(Boolean.TRUE.equals(debug));
      PSSDK.init(appContext, builder.build(), new PSSDK.PSSDKInitListener() {
        @Override
        public void onInitFinished(boolean success, PSSDK.ErrorInfo errorInfo) {
          new Handler(Looper.getMainLooper()).post(() -> result.success(success));
        }
      });
    } catch (Throwable t) {
      result.error("INIT_ERROR", t.getMessage(), null);
    }
  }

  private void setEligibleAudience(@NonNull MethodCall call, @NonNull Result result) {
    Boolean eligible = asBoolean(safeMap(call.arguments).get("eligible"));
    try {
      PSSDK.setEligibleAudience(eligible != null && eligible);
      result.success(null);
    } catch (Throwable t) {
      result.error("ELIGIBLE_ERROR", t.getMessage(), null);
    }
  }

  @SuppressWarnings("unchecked")
  private void setContentLanguages(@NonNull MethodCall call, @NonNull Result result) {
    Object langsObj = safeMap(call.arguments).get("languages");
    List<String> langs = new ArrayList<>();
    if (langsObj instanceof List) {
      for (Object o : (List<?>) langsObj) {
        if (o != null) langs.add(String.valueOf(o));
      }
    }
    try {
      PSSDK.setContentLanguages(langs);
      result.success(null);
    } catch (Throwable t) {
      result.error("LANG_ERROR", t.getMessage(), null);
    }
  }

  private void setContentLanguage(@NonNull MethodCall call, @NonNull Result result) {
    String language = asString(safeMap(call.arguments).get("language"));
    List<String> langs = new ArrayList<>();
    if (language != null && !language.isEmpty()) langs.add(language);
    try {
      PSSDK.setContentLanguages(langs);
      result.success(null);
    } catch (Throwable t) {
      result.error("LANG_ERROR", t.getMessage(), null);
    }
  }

  @SuppressWarnings("deprecation")
  private String getCurrentLanguage() {
    try {
      java.util.Locale locale;
      android.content.res.Configuration config = appContext.getResources().getConfiguration();
      if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        locale = config.getLocales().get(0);
      } else {
        // Use deprecated API for Android versions below N
        locale = config.locale;
      }
      String country = locale != null ? locale.getCountry() : null;
      if (country == null || country.isEmpty()) return "US";
      return country.toUpperCase();
    } catch (Throwable t) {
      return "US";
    }
  }

  private void requestFeedList(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    int index = asInt(args.get("index"), 1);
    int count = asInt(args.get("count"), 10);
    try {
      PSSDK.requestFeedList(index, count, new PSSDK.FeedListResultListener() {
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) {
          String msg = String.valueOf(errorInfo);
          new Handler(Looper.getMainLooper()).post(() -> result.error("FEED_ERROR", msg, null));
        }

        @Override
        public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay> res) {
          Map<String, Object> map = new HashMap<>();
          List<Map<String, Object>> items = new ArrayList<>();
          if (res != null && res.dataList != null) {
            for (ShortPlay sp : res.dataList) {
              items.add(convertShortPlay(sp));
            }
          }
          map.put("list", items);
          map.put("hasMore", res != null && res.hasMore);
          new Handler(Looper.getMainLooper()).post(() -> result.success(map));
        }
      });
    } catch (Throwable t) {
      result.error("FEED_ERROR", t.getMessage(), null);
    }
  }

  @SuppressWarnings("unchecked")
  private void requestFeedListWithFilters(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    int index = asInt(args.get("index"), 1);
    int count = asInt(args.get("count"), 20);
    List<Long> categoryIds = new ArrayList<>();
    List<Long> shortplayIds = new ArrayList<>();
    try {
      Object cat = args.get("categoryIds");
      if (cat instanceof List) {
        for (Object o : (List<?>) cat) {
          try { categoryIds.add(Long.parseLong(String.valueOf(o))); } catch (Throwable ignored) {}
        }
      }
      Object sids = args.get("shortplayIds");
      if (sids instanceof List) {
        for (Object o : (List<?>) sids) {
          try { shortplayIds.add(Long.parseLong(String.valueOf(o))); } catch (Throwable ignored) {}
        }
      }
      PSSDK.requestFeedListByCategoryIds(
          categoryIds.isEmpty() ? null : new java.util.ArrayList<>(categoryIds),
          shortplayIds.isEmpty() ? null : new java.util.ArrayList<>(shortplayIds),
          index,
          count,
          new PSSDK.FeedListResultListener() {
            @Override
            public void onFail(PSSDK.ErrorInfo errorInfo) {
              String msg = String.valueOf(errorInfo);
              new Handler(Looper.getMainLooper()).post(() -> result.error("FILTER_ERROR", msg, null));
            }

            @Override
            public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay> res) {
              Map<String, Object> map = new HashMap<>();
              List<Map<String, Object>> items = new ArrayList<>();
              if (res != null && res.dataList != null) {
                for (ShortPlay sp : res.dataList) {
                  items.add(convertShortPlay(sp));
                }
              }
              map.put("list", items);
              map.put("hasMore", res != null && res.hasMore);
              new Handler(Looper.getMainLooper()).post(() -> result.success(map));
            }
          }
      );
    } catch (Throwable t) {
      result.error("FILTER_ERROR", t.getMessage(), null);
    }
  }

  private void requestPopularDrama(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    int index = asInt(args.get("index"), 1);
    int count = asInt(args.get("count"), 20);
    try {
      PSSDK.requestPopularDrama(index, count, new PSSDK.FeedListResultListener() {
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) {
          String msg = String.valueOf(errorInfo);
          new Handler(Looper.getMainLooper()).post(() -> result.error("POPULAR_ERROR", msg, null));
        }

        @Override
        public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay> res) {
          Map<String, Object> map = new HashMap<>();
          List<Map<String, Object>> items = new ArrayList<>();
          if (res != null && res.dataList != null) {
            for (ShortPlay sp : res.dataList) {
              items.add(convertShortPlay(sp));
            }
          }
          map.put("list", items);
          map.put("hasMore", res != null && res.hasMore);
          new Handler(Looper.getMainLooper()).post(() -> result.success(map));
        }
      });
    } catch (Throwable t) {
      result.error("POPULAR_ERROR", t.getMessage(), null);
    }
  }

  private void requestNewFeedList(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    int index = asInt(args.get("index"), 1);
    int count = asInt(args.get("count"), 20);
    try {
      PSSDK.requestNewDrama(index, count, new PSSDK.FeedListResultListener() {
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) {
          String msg = String.valueOf(errorInfo);
          new Handler(Looper.getMainLooper()).post(() -> result.error("NEW_ERROR", msg, null));
        }

        @Override
        public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay> res) {
          Map<String, Object> map = new HashMap<>();
          List<Map<String, Object>> items = new ArrayList<>();
          if (res != null && res.dataList != null) {
            for (ShortPlay sp : res.dataList) {
              items.add(convertShortPlay(sp));
            }
          }
          map.put("list", items);
          map.put("hasMore", res != null && res.hasMore);
          new Handler(Looper.getMainLooper()).post(() -> result.success(map));
        }
      });
    } catch (Throwable t) {
      result.error("NEW_ERROR", t.getMessage(), null);
    }
  }

  private void requestDramaWithTag(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    int tag = asInt(args.get("tag"), 0);
    int index = asInt(args.get("index"), 1);
    int count = asInt(args.get("count"), 20);
    try {
      PSSDK.requestDramaByTag(tag, index, count, new PSSDK.FeedListResultListener() {
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) {
          String msg = String.valueOf(errorInfo);
          new Handler(Looper.getMainLooper()).post(() -> result.error("TAG_ERROR", msg, null));
        }

        @Override
        public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay> res) {
          Map<String, Object> map = new HashMap<>();
          List<Map<String, Object>> items = new ArrayList<>();
          if (res != null && res.dataList != null) {
            for (ShortPlay sp : res.dataList) {
              items.add(convertShortPlay(sp));
            }
          }
          map.put("list", items);
          map.put("hasMore", res != null && res.hasMore);
          new Handler(Looper.getMainLooper()).post(() -> result.success(map));
        }
      });
    } catch (Throwable t) {
      result.error("TAG_ERROR", t.getMessage(), null);
    }
  }

  private void getCategoryList(@NonNull MethodCall call, @NonNull Result result) {
    String language = asString(safeMap(call.arguments).get("language"));
    try {
      PSSDK.requestCategoryList(language != null ? language : "en", new PSSDK.CategoryListResultListener() {
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) {
          String msg = String.valueOf(errorInfo);
          new Handler(Looper.getMainLooper()).post(() -> result.error("CATEGORY_ERROR", msg, null));
        }

        @Override
        public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay.ShortPlayCategory> res) {
          List<Map<String, Object>> items = new ArrayList<>();
          if (res != null && res.dataList != null) {
            for (ShortPlay.ShortPlayCategory c : res.dataList) {
              Map<String, Object> m = new HashMap<>();
              try { m.put("category_id", c.id); } catch (Throwable ignored) {}
              try { if (c.name != null) m.put("category_name", c.name); } catch (Throwable ignored) {}
              items.add(m);
            }
          }
          List<Map<String, Object>> finalItems = items;
          new Handler(Looper.getMainLooper()).post(() -> result.success(finalItems));
        }
      });
    } catch (Throwable t) {
      result.error("CATEGORY_ERROR", t.getMessage(), null);
    }
  }

  private void requestSearchDrama(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    String keyword = asString(args.get("keyword"));
    boolean isFuzzy = Boolean.TRUE.equals(asBoolean(args.get("isFuzzy")));
    int index = asInt(args.get("index"), 1);
    int count = asInt(args.get("count"), 20);
    try {
      PSSDK.searchDrama(keyword != null ? keyword : "", isFuzzy, index, count, new PSSDK.FeedListResultListener() {
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) {
          String msg = String.valueOf(errorInfo);
          new Handler(Looper.getMainLooper()).post(() -> result.error("SEARCH_ERROR", msg, null));
        }

        @Override
        public void onSuccess(PSSDK.FeedListLoadResult<ShortPlay> res) {
          Map<String, Object> map = new HashMap<>();
          List<Map<String, Object>> items = new ArrayList<>();
          if (res != null && res.dataList != null) {
            for (ShortPlay sp : res.dataList) {
              items.add(convertShortPlay(sp));
            }
          }
          map.put("list", items);
          map.put("hasMore", res != null && res.hasMore);
          new Handler(Looper.getMainLooper()).post(() -> result.success(map));
        }
      });
    } catch (Throwable t) {
      result.error("SEARCH_ERROR", t.getMessage(), null);
    }
  }

  private void checkPlayStatus(@NonNull MethodCall call, @NonNull Result result) {
    try {
      PSSDK.checkPlayStatus(new PSSDK.ServiceCheckResultListener() {
        @Override
        public void onCheckResult(PSSDK.ServiceAvailableResult r) {
          int code = 0;
          if (r == PSSDK.ServiceAvailableResult.SUPPORT) code = 1;
          else if (r == PSSDK.ServiceAvailableResult.NOT_SUPPORT) code = 2;
          final int finalCode = code;
          new Handler(Looper.getMainLooper()).post(() -> result.success(finalCode));
        }
      });
    } catch (Throwable t) {
      result.error("CHECK_ERROR", t.getMessage(), null);
    }
  }

  private void setCollected(@NonNull MethodCall call, @NonNull Result result) {
    Map<String, Object> args = safeMap(call.arguments);
    boolean collected = Boolean.TRUE.equals(asBoolean(args.get("collected")));
    long shortplayId = 0L;
    try { shortplayId = Long.parseLong(String.valueOf(args.get("shortplayId"))); } catch (Throwable ignored) {}
    try {
      PSSDK.setCollected(shortplayId, collected, new PSSDK.ActionResultListener() {
        @Override
        public void onSuccess() { new Handler(Looper.getMainLooper()).post(() -> result.success(true)); }
        @Override
        public void onFail(PSSDK.ErrorInfo errorInfo) { new Handler(Looper.getMainLooper()).post(() -> result.success(false)); }
      });
    } catch (Throwable t) {
      result.error("COLLECT_ERROR", t.getMessage(), null);
    }
  }

  private void clearLocalCache(@NonNull MethodCall call, @NonNull Result result) {
    try {
      // 当前 SDK 暂无直接清缓存 API，返回成功占位
      result.success(null);
    } catch (Throwable t) {
      result.error("CLEAR_CACHE_ERROR", t.getMessage(), null);
    }
  }

  private Map<String, Object> convertShortPlay(ShortPlay sp) {
    Map<String, Object> m = new HashMap<>();
    if (sp == null) return m;
    try {
      // Align keys to Dart models.dart expectations
      m.put("id", sp.id);
      if (sp.title != null) m.put("title", sp.title);
      m.put("total", sp.total);
      m.put("firstOnlineTime", sp.firstOnlineTime);
      try {
        int state = sp.progressState;
        m.put("progress_state", state);
      } catch (Throwable ignored) {
        m.put("progress_state", 2);
      }
      if (sp.desc != null) m.put("desc", sp.desc);
      if (sp.coverImage != null) m.put("cover_image", sp.coverImage);
      try {
        if (sp.language != null) m.put("language", sp.language);
      } catch (Throwable ignored) {
        m.put("language", null);
      }
      try {
        java.util.ArrayList<ShortPlay.ShortPlayCategory> cats = sp.categories;
        if (cats != null && !cats.isEmpty()) {
          java.util.ArrayList<java.util.HashMap<String, Object>> catList = new java.util.ArrayList<>();
          for (ShortPlay.ShortPlayCategory c : cats) {
            java.util.HashMap<String, Object> cat = new java.util.HashMap<>();
            cat.put("id", c.id);
            if (c.name != null) cat.put("name", c.name);
            cat.put("count", c.count);
            catList.add(cat);
          }
          // Also keep first category for backward compatibility
          if (!catList.isEmpty()) {
            m.put("categories", catList);
          }
        }
      } catch (Throwable ignored) {
        m.put("categories", null);
      }

      try {
        java.util.ArrayList<ShortPlay.Tag> tags = sp.tags;
        if (tags != null && !tags.isEmpty()) {
          java.util.ArrayList<java.util.HashMap<String, Object>> tagList = new java.util.ArrayList<>();
          for (ShortPlay.Tag t : tags) {
            java.util.HashMap<String, Object> tag = new java.util.HashMap<>();
            tag.put("tag_id", t.id);
            try {
              if (t.name != null) tag.put("tag_name", t.name);
            } catch (Throwable ignored) {
              tag.put("tag_name", null);
            }
            tagList.add(tag);
          }
          m.put("tags", tagList);
        }
      } catch (Throwable ignored) {
        m.put("tags", null);
      }

      m.put("totalCollectCount", sp.totalCollectCount);
      m.put("isCollected", sp.isCollected);
      m.put("sType", sp.sType);

      java.util.ArrayList<java.util.HashMap<String, Object>> episodeList = new java.util.ArrayList<>();
      for (int i = 0; i < sp.episodes.size(); i++) {
        java.util.HashMap<String, Object> e = new java.util.HashMap<>();
        e.put("index",sp.episodes.get(i).index);
        e.put("vid",sp.episodes.get(i).vid);
        e.put("country",sp.episodes.get(i).country);
        e.put("expireTime",sp.episodes.get(i).expireTime);
        e.put("id",sp.episodes.get(i).id);
        e.put("totalLikeCount",sp.episodes.get(i).totalLikeCount);
        e.put("isLiked",sp.episodes.get(i).isLiked);
        e.put("playInfoListData",sp.episodes.get(i).playInfoListData);
        episodeList.add(e);
      }
      m.put("episodes",episodeList);
    } catch (Throwable ignored) {}
    return m;
  }

  @SuppressWarnings("unchecked")
  private static Map<String, Object> safeMap(Object obj) {
    if (obj instanceof Map) return (Map<String, Object>) obj;
    return new HashMap<>();
  }

  private static String asString(Object o) { return o == null ? null : String.valueOf(o); }
  private static Boolean asBoolean(Object o) { return o == null ? null : (o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(String.valueOf(o))); }
  private static int asInt(Object o, int def) {
    try { return o == null ? def : Integer.parseInt(String.valueOf(o)); } catch (Exception e) { return def; }
  }
}
